import 'dart:convert';

import 'package:aero_frisbee/app/model/login_respose_model/login_respose_model.dart';
import 'package:aero_frisbee/app/model/login_respose_model/user_info_model.dart';
import 'package:aero_frisbee/app/req/af_req_api.dart';
import 'package:aero_frisbee/app/store/app_store.dart';
import 'package:get_it/get_it.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:rongcloud_im_wrapper_plugin/rongcloud_im_wrapper_plugin.dart';
import 'package:shared_preferences/shared_preferences.dart';

import 'af_app_state.dart';

part 'app_cache_state.g.dart';

@Riverpod(keepAlive: true)
SharedPreferences appPrefs(AppPrefsRef ref) {
  throw UnimplementedError();
}

@Riverpod(keepAlive: true)
RCIMIWEngine? curEngine(CurEngineRef ref) {
  return ref.watch(curEngineFutureProvider).maybeWhen(
        orElse: () => null,
        data: (data) => data,
      );
}

@Riverpod(keepAlive: true)
FutureOr<RCIMIWEngine?> curEngineFuture(CurEngineFutureRef ref) async {
  final appLoginState = ref.watch(appCacheServiceProvider);

  final loginInfo = appLoginState.maybeWhen(
    data: ((data) => data.maybeWhen(
          logined: (user) => user,
          orElse: () => null,
        )),
    orElse: () => null,
  );
  if (loginInfo != null) {
    var options = RCIMIWEngineOptions.create();
    final engine = await RCIMIWEngine.create(loginInfo.rck ?? '', options);
    engine.onConnectionStatusChanged = (RCIMIWConnectionStatus? status) {};
    await engine.connect(
      loginInfo.tongcloudToken ?? '',
      5000000,
      callback: RCIMIWConnectCallback(
        onDatabaseOpened: (int? code) {
          // print("xxx  RCIM onDatabaseOpened :$code ");
        },
        onConnected: (int? code, String? userId) {
          // print("xxx  RCIM connect code:$code userId:$userId");
        },
      ),
    );
    return engine;
  }
  return null;
}

@Riverpod(keepAlive: true)
class AppCacheService extends _$AppCacheService {
  @override
  FutureOr<AfAppState> build() async {
    return loadCache();
  }

  Future<AfAppState> loadCache() async {
    final prefs = ref.read(appPrefsProvider);
    final userStr = prefs.getString('login.respose.key');
    if (userStr != null) {
      final user = LoginResposeModel.fromJson(jsonDecode(userStr));
      final api = ref.watch(appApiProvider);
      final isOk = await api.isValidToken(
        token: user.token ?? '',
      );
      if (isOk) {
        final retUsr = await api.launchByLoginRespose(user);
        asyncUpdateUserInfo(userid: user.userInfoModel?.userId ?? '');
        return AfAppState.logined(retUsr);
      } else {
        return const AfAppState.toLogin();
      }
    }
    return const AfAppState.toLogin();
  }

  logined(LoginResposeModel respose) {
    state = AsyncData(AfAppState.logined(respose));
    final prefs = ref.read(appPrefsProvider);
    GetIt.I.get<AppStore>().token = respose.token ?? '';
    GetIt.I.get<AppStore>().userInfo = respose.userInfoModel;
    prefs.setString('login.respose.key', jsonEncode(respose.toJson()));
  }

  toggleAutoTranslate() {
    final loginInfo = state.maybeWhen(
      orElse: () => null,
      data: (data) => data.maybeWhen(
        logined: (loginResposeModel) => loginResposeModel,
        orElse: () => null,
      ),
    );
    if (loginInfo != null) {
      logined(loginInfo.copyWith(autoTranslate: !loginInfo.autoTranslate));
    }
  }

  asyncUpdateUserInfo({String? userid}) async {
    // final api = ref.read(appApiProvider);
    // final curUserInfo = state.maybeWhen(
    //   orElse: () => null,
    //   data: (data) => data.maybeWhen(
    //     logined: (loginResposeModel) => loginResposeModel.userInfoModel,
    //     orElse: () => null,
    //   ),
    // );
    // final userInfo =
    //     await api.fetchUserInfo(userId: userid ?? (curUserInfo?.userId ?? ''));
    // updateUserInfo(userInfo: userInfo);
  }

  updateUserInfo({required UserInfoModel userInfo}) {
    final loginInfo = state.maybeWhen(
      orElse: () => null,
      data: (data) => data.maybeWhen(
        logined: (loginResposeModel) => loginResposeModel,
        orElse: () => null,
      ),
    );
    if (loginInfo != null) {
      logined(loginInfo.copyWith(userInfoModel: userInfo));
    }
  }

  updateAvailableCoins(int availableCoins) {
    final loginInfo = state.maybeWhen(
      orElse: () => null,
      data: (data) => data.maybeWhen(
        logined: (loginResposeModel) => loginResposeModel,
        orElse: () => null,
      ),
    );
    if (loginInfo != null) {
      final curUserInfo = loginInfo.userInfoModel;
      if (curUserInfo != null) {
        ///更新下本地缓存
        logined(loginInfo.copyWith(
            userInfoModel: curUserInfo.copyWith(
                availableCoins:
                    (curUserInfo.availableCoins ?? 0) + availableCoins)));
      }
    }
  }

  logout() {
    final prefs = ref.read(appPrefsProvider);
    prefs.remove('login.respose.key');
    GetIt.I.get<AppStore>().clear();
    state = const AsyncData(AfAppState.toLogin());
  }
}

@Riverpod(keepAlive: true)
LoginResposeModel? curlUserInfo(CurlUserInfoRef ref) {
  return ref.watch(appCacheServiceProvider).maybeWhen(
        orElse: () => null,
        data: (data) => data.maybeWhen(
          logined: (user) => user,
          orElse: () => null,
        ),
      );
}
